/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.etrs.formathlon.control.security;

import javax.ejb.EJB;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import net.etrs.formathlon.entity.utilisateur.Utilisateur;
import net.etrs.formathlon.persistance.utilisateur.UtilisateurFacade;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import net.etrs.formathlon.metier.service.uc6.authentificationLDAP.ADTUserDetails;
import org.springframework.security.core.context.SecurityContextHolder;
import net.etrs.formathlon.metier.utils.constantes.Parametres;
import net.etrs.formathlon.metier.utils.constantes.RoleSpring;
import org.apache.commons.lang3.StringUtils;

/**
 * Bean qui va gérer tous ce qui touche la securité; l'accées et la validation de la 
 * page de login, la déconexion ainsi que l'accés au information du principal.
 * @author OPIF
 */
@ManagedBean
@SessionScoped
public class LoginControler {

    @EJB
    private UtilisateurFacade facade;
    
    private static final String SPRING_SECURITY_LOGIN = "/j_spring_security_check";
    private static final String SPRING_SECURITY_LOGOUT = "/j_spring_security_logout";
    private static final String SPRING_SECURITY_PAGE_DEFAULT_LOGIN = "/spring_security_login";
    
    /**
     * Déconnexion
     * @return La redirection
     * @throws ServletException
     * @throws IOException 
     */
    public String logOut() throws ServletException, IOException {
        this.doForward(SPRING_SECURITY_LOGOUT);
        return null;
    }

    /**
     * 
     * @return l'utilisateur correspondant au principal.
     */
    public Utilisateur getUtilisateurConnecte(){
        return facade.getUtilisateurByLogin(getLogin());
    }

    /**
     * Est-ce que l'utilisateur possède le rôle en paramètre?.
     * @param role
     * @return 
     */
    private boolean isInRole(String role) {

        return FacesContext.getCurrentInstance().getExternalContext().isUserInRole(role);
    }

    /**
     * Est-ce que l'utilisateur possède au moins un des rôles en paramètre?.
     * @param roles
     * @return 
     */
    private boolean isInRoles(List<String> roles) {
        boolean retour = false;
        String role;
        Iterator it = roles.iterator();
        while (!retour && it.hasNext()) {
            role = (String) it.next();
            retour = isInRole(role);
        }
        return retour;
    }

    /**
     * Renvoi un dispatcher pour aller vers la page en paramètre.
     * @param ctx
     * @param springAction
     * @return RequestDispatcher
     */
    private RequestDispatcher getDispatcher(ExternalContext ctx, String springAction) {
        return ((ServletRequest) ctx.getRequest()).getRequestDispatcher(springAction);
    }

    /**
     * Methode privée de renvoi vers la page don't url est en paramètre.
     * @param url
     * @throws ServletException
     * @throws IOException 
     */
    private void doForward(String url) throws ServletException, IOException {
        ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext();
        RequestDispatcher dispatcher = this.getDispatcher(ctx, url);
        dispatcher.forward((ServletRequest) ctx.getRequest(), (ServletResponse) ctx.getResponse());
        FacesContext.getCurrentInstance().responseComplete();
    }

    /**
     * Tentative de log avec les informations de la page de login.
     * @return null
     * @throws IOException
     * @throws ServletException 
     */
    public String doLogin() throws IOException, ServletException {
        this.doForward(SPRING_SECURITY_LOGIN);
        return null;
    }
    
    /**
     * Envoie vers la page de login.
     * @return null
     * @throws IOException
     * @throws ServletException 
     */
    public String doPageLogin() throws IOException, ServletException {
        this.doForward(SPRING_SECURITY_PAGE_DEFAULT_LOGIN);
        return null;
    }
    
    /**
     * 
     * @return si un ADTUserDetails est connecté.
     */
    public boolean isAuthentifie() {
        try{
            if (SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString().equals("anonymousUser")) {
                return false;
            }
            return true;
        }
        catch(NullPointerException ex){
            return false;
        }
    }

    /**
     * 
     * @return le nom formaté du ADTUserDetails
     */
    public String getDisplayName() {

        if (isAuthentifie()) {
            String grade = ((ADTUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getGrade().toUpperCase();
            String nom = ((ADTUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getNom().toUpperCase();
            String prenom = StringUtils.capitalize(((ADTUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getPrenom());            
            return String.format("%s %s %s", grade, nom, prenom);
        } else {
            return "";
        }
    }

    /**
     * 
     * @return le login du principal.
     */
    public String getLogin() {
        if (isAuthentifie()) {
            return ((ADTUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getLogin();
        } else {
            return "";
        }
    }

    /**
     * Savoir s'il est chef peu importe de quoi.
     * @return Vrai si la personne connectée est chef (dir / div / cours)
     */
    public boolean isChef() {
        return isInRoles(Parametres.getListRolesChef());
    }

    /**
     * Savoir s'il est chef de division.
     * @return Vrai si la personne connectée est chef de division
     */
    public boolean isChefDivision() {
        return isInRole(RoleSpring.ROLE_CHEF_DIV.getLibelle());
    }
    
    /**
     * Savoir s'il est chef de direction.
     * @return Vrai si la personne connectée est chef de direction
     */
    public boolean isChefDirection() {
        return isInRole(RoleSpring.ROLE_CHEF_DIR.getLibelle());
    }

    /**
     * Savoir s'il est chef de cours.
     * @return Vrai si la personne connectée est chef de cours
     */
    public boolean isChefCours() {
        return isInRole(RoleSpring.ROLE_CHEF_COURS.getLibelle());
    }

    /**
     * Savoir s'il est gestionnaire.
     * @return Vrai si la personne connectée est membre du bens (gestionnaire)
     */
    public boolean isGestionnaire() {
        return isInRole(RoleSpring.ROLE_GEST.getLibelle());
    }

    /**
     * Savoir s'il est formateur avancé.
     * @return Vrai si la personne connectée est formateur avancé
     */
    public boolean isInstructeur() {
        return facade.isInstructeur(getUtilisateurConnecte());
    }

    /**
     * Savoir s'il est formateur.
     * @return Vrai si la personne connectée est utilisateur
     */
    public boolean isUtilisateur() {
        return isInRole(RoleSpring.ROLE_UTIL.getLibelle());
    }

    /**
     * Savoir s'il est administrateur.
     * @return Vrai si la personne connectée est Admin
     */
    public boolean isAdmin() {
        return isInRole(RoleSpring.ROLE_ADMIN.getLibelle());
    }
}
